﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace Gmantis.Controls.Chart
{
    public enum LegendPosition
    {
        Left,
        Right,
        Top,
        Bottom,
        TopLeft,
        TopCenter,
        TopRight,
        BottomLeft,
        BottomCenter,
        BottomRight
    }

    public class ChartLegend : System.Windows.Controls.ItemsControl
    {
        // Fields
        private Chart _parent;
        private LegendPosition _position;
        public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(ChartLegend), null);
        public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register("Orientation", typeof(Orientation), typeof(ChartLegend), new PropertyMetadata(Orientation.Vertical, new PropertyChangedCallback(ChartLegend.OnOrientationChanged)));
        public static readonly DependencyProperty OverlapChartProperty = DependencyProperty.Register("OverlapChart", typeof(bool), typeof(ChartLegend), new PropertyMetadata(false, new PropertyChangedCallback(ChartLegend.OnOverlapChartChanged)));
        private StackPanel sp;
        public static readonly DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(object), typeof(ChartLegend), new PropertyMetadata(null, new PropertyChangedCallback(ChartLegend.OnTitleChanged)));

        // Methods
        public ChartLegend()
        {
            RoutedEventHandler handler = null;
            this._position = LegendPosition.Right;
            base.DefaultStyleKey = typeof(ChartLegend);
            base.VerticalContentAlignment = VerticalAlignment.Center;
            if (handler == null)
            {
                handler = (s, e) => this.UpdatePosition();
            }
            base.Loaded += handler;
        }

        private void _parent_LegendChanged(object sender, EventArgs e)
        {
            base.ItemsSource = null;
            base.ItemsSource = this._parent.LegendItems;
        }

        private static void OnOrientationChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            ChartLegend legend = (ChartLegend)obj;
            if (legend.sp != null)
            {
                legend.sp.Orientation = legend.Orientation;
            }
        }

        private static void OnOverlapChartChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            ((ChartLegend)obj).UpdatePosition();
        }

        private static void OnTitleChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
        }

        protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
        {
            if (element != null)
            {
                this.sp = VisualTreeHelper.GetParent(element) as StackPanel;
                if ((this.sp != null) && (this.sp.Orientation != this.Orientation))
                {
                    this.sp.Orientation = this.Orientation;
                }
            }
            base.PrepareContainerForItemOverride(element, item);
        }

        private void UpdatePosition()
        {
            switch (this.Position)
            {
                case LegendPosition.Left:
                    Grid.SetColumn(this, this.OverlapChart ? 1 : 0);
                    Grid.SetRow(this, 1);
                    base.HorizontalAlignment = HorizontalAlignment.Left;
                    base.VerticalAlignment = VerticalAlignment.Center;
                    return;

                case LegendPosition.Right:
                    Grid.SetColumn(this, this.OverlapChart ? 1 : 2);
                    Grid.SetRow(this, 1);
                    base.HorizontalAlignment = HorizontalAlignment.Right;
                    base.VerticalAlignment = VerticalAlignment.Center;
                    return;

                case LegendPosition.Top:
                case LegendPosition.TopCenter:
                    Grid.SetColumn(this, 1);
                    Grid.SetRow(this, this.OverlapChart ? 1 : 0);
                    base.HorizontalAlignment = HorizontalAlignment.Center;
                    base.VerticalAlignment = VerticalAlignment.Top;
                    return;

                case LegendPosition.Bottom:
                case LegendPosition.BottomCenter:
                    Grid.SetColumn(this, 1);
                    Grid.SetRow(this, this.OverlapChart ? 1 : 2);
                    base.HorizontalAlignment = HorizontalAlignment.Center;
                    base.VerticalAlignment = VerticalAlignment.Bottom;
                    return;

                case LegendPosition.TopLeft:
                    Grid.SetColumn(this, 1);
                    Grid.SetRow(this, this.OverlapChart ? 1 : 0);
                    base.HorizontalAlignment = HorizontalAlignment.Left;
                    base.VerticalAlignment = VerticalAlignment.Top;
                    return;

                case LegendPosition.TopRight:
                    Grid.SetColumn(this, 1);
                    Grid.SetRow(this, this.OverlapChart ? 1 : 0);
                    base.HorizontalAlignment = HorizontalAlignment.Right;
                    base.VerticalAlignment = VerticalAlignment.Top;
                    return;

                case LegendPosition.BottomLeft:
                    Grid.SetColumn(this, 1);
                    Grid.SetRow(this, this.OverlapChart ? 1 : 2);
                    base.HorizontalAlignment = HorizontalAlignment.Left;
                    base.VerticalAlignment = VerticalAlignment.Bottom;
                    return;

                case LegendPosition.BottomRight:
                    Grid.SetColumn(this, 1);
                    Grid.SetRow(this, this.OverlapChart ? 1 : 2);
                    base.HorizontalAlignment = HorizontalAlignment.Right;
                    base.VerticalAlignment = VerticalAlignment.Bottom;
                    return;
            }
        }

        // Properties
        public Chart Chart
        {
            get
            {
                return this._parent;
            }
            set
            {
                if (this._parent != value)
                {
                    if (this._parent != null)
                    {
                        this._parent.LegendChanged -= new EventHandler(this._parent_LegendChanged);
                    }
                    this._parent = value;
                    if (this._parent != null)
                    {
                        this._parent.LegendChanged += new EventHandler(this._parent_LegendChanged);
                        base.ItemsSource = this._parent.LegendItems;
                    }
                    else
                    {
                        base.ItemsSource = null;
                    }
                    this._parent.InitLegendBindings(this);
                }
            }
        }

        public CornerRadius CornerRadius
        {
            get
            {
                return (CornerRadius)base.GetValue(CornerRadiusProperty);
            }
            set
            {
                base.SetValue(CornerRadiusProperty, value);
            }
        }

        public Orientation Orientation
        {
            get
            {
                return (Orientation)base.GetValue(OrientationProperty);
            }
            set
            {
                base.SetValue(OrientationProperty, value);
            }
        }

        public bool OverlapChart
        {
            get
            {
                return (bool)base.GetValue(OverlapChartProperty);
            }
            set
            {
                base.SetValue(OverlapChartProperty, value);
            }
        }

        public LegendPosition Position
        {
            get
            {
                return this._position;
            }
            set
            {
                if (this._position != value)
                {
                    this._position = value;
                    this.UpdatePosition();
                }
            }
        }

        public object Title
        {
            get
            {
                return base.GetValue(TitleProperty);
            }
            set
            {
                base.SetValue(TitleProperty, value);
            }
        }
    }
}
